#include "core_headers.hpp"
#include "Channel.hpp"
// 使用环形缓冲区(60槽位)实现时间轮
// 通过智能指针管理任务生命周期
// 利用析构函数统一处理任务执行和清理
// 支持任务刷新和取消机制
// 特别适合非活跃连接超时处理场景

// 封装定时任务的唯一标识、超时时间、执行逻辑和取消状态
// 通过智能指针管理生命周期，析构时自动清理相关资源
class EventLoop;
using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimerTask // 定时任务的载体，封装任务逻辑和生命周期控制
{
public:
	TimerTask(uint64_t id, uint32_t timeout, const TaskFunc &task)
		: _id(id), _timeout(timeout), _task(task), _cancel(false)
	{
	}
	~TimerTask()
	{
		if (_cancel == false)
			_task();	// 取消定时任务销毁要在这任务模块完成，如果在时间轮完成还不是相当于销毁任务
		_releasetack(); // 把被weak_ptr管理起来的shared_ptr从_clone中移除，只有shared_ptr计数为0时才会进入析构函数
	}
	void SetReleaseTask(const ReleaseFunc &releasetack)
	{
		_releasetack = releasetack;
	}
	void Cancel() { _cancel = true; }
	int TimeOut() { return _timeout; }

private:
	uint64_t _id;			  // 定时任务id
	uint32_t _timeout;		  // 超时时间
	bool _cancel;			  // false表示不取消非活跃链接销毁，true表示取消
	TaskFunc _task;			  // 定时器对象要执行的定时任务
	ReleaseFunc _releasetack; // //用于删除TimerWheel中保存的定时器对象信息
};

// 维护一个环形时间轮结构，实现任务的定时调度
// 使用智能指针管理任务生命周期，避免循环引用
// 支持任务的添加、刷新、执行和取消操作
using SharTask = std::shared_ptr<TimerTask>;
using WeakTask = std::weak_ptr<TimerTask>;
class TimerWheel // 时间轮管理器，负责任务的调度、执行和管理
{
public:
	TimerWheel(EventLoop *loop)
		: _tick(0), _capacity(60), _wheel(_capacity), _loop(loop), _timerfd(CreateTimerfd()), _timer_channel(new Channel(_loop, _timerfd))
	{
		_timer_channel->SetReadCallback(std::bind(&TimerWheel::OnTimer, this));
		_timer_channel->EnableReadableEvent();
	}
	void TaskAdd(uint64_t id, uint32_t timeout, const TaskFunc &task);
	void RefreshTask(uint64_t id);
	void TaskCancel(uint64_t id);
	bool hashtimer(uint64_t id)
	{
		auto it = _clone.find(id);
		if (it == _clone.end())
		{
			DEL_LOG("没有找到");
			return false;
		}
		return true;
	}

private:
	void Remove(uint64_t id)
	{
		auto it = _clone.find(id);
		if (it != _clone.end())
		{
			// 找到了 进行移除
			_clone.erase(id);
		}
	}
	int CreateTimerfd()
	{
		int timerfd = ::timerfd_create(CLOCK_MONOTONIC, 0);
		if (timerfd < 0)
		{
			ERR_LOG("timerfd_create error,%d,%s", errno, strerror(errno));
			abort();
		}
		struct itimerspec n;
		n.it_value.tv_sec = 1;
		n.it_value.tv_nsec = 0;
		n.it_interval.tv_sec = 1;
		n.it_interval.tv_nsec = 1;
		int ret = ::timerfd_settime(timerfd, 0, &n, nullptr);
		if (ret < 0)
		{
			ERR_LOG("timerfd_settime error,%d,%s", errno, strerror(errno));
			abort();
		}
		return timerfd;
	}
	int ReadTImerfd()
	{
		uint64_t timed = 0;
		ssize_t n = ::read(_timerfd, &timed, sizeof(timed));
		if (n < 0)
		{
			ERR_LOG("timerfd read error,%d,%s", errno, strerror(errno));
			abort();
		}
		return timed;
	}
	void RunTimerTask() // 这个函数应该每秒钟被执行一次，相当于秒针向后走了一步
	{
		_tick = (_tick + 1) % _capacity;
		_wheel[_tick].clear(); // 清空指定位置的数组，就会把数组中保存的所有管理定时器对象的shared_ptr释放掉
	}
	// 	考虑以下场景：
	//  1.定时器每 1 秒触发一次事件。
	//  2.某次事件处理耗时 3 秒，期间定时器超时 3 次。
	//  3.当程序恢复处理定时器事件时，ReadTimefd() 返回 times = 3，表示积压了 3 次超时。
	//  4.通过循环 RunTimerTask() 3 次，时间轮指针 _tick 会连续移动 3 格，保持与实际时间同步。
	//  若不处理积压次数，时间轮指针会滞后，导致定时任务延迟执行或丢失。
	void OnTimer()
	{
		// 获取超时次数
		int n = ReadTImerfd();
		// 确保即使系统繁忙导致定时器事件处理延迟，也能通过批量处理恢复时间轮的准确性
		for (int i = 0; i < n; i++)
		{
			RunTimerTask();
		}
	}
	void TaskAddInLoop(uint64_t id, uint32_t timeout, const TaskFunc &task) // 添加定时任务
	{
		SharTask pt(new TimerTask(id, timeout, task));
		pt->SetReleaseTask(std::bind(&TimerWheel::Remove, this, id)); // 插入 释放保存的定时任务 函数，sherad_ptr管理的定时任务计数为0时，进行释放执行析构函数
		int ti = (_tick + timeout) % _capacity;
		_wheel[ti].push_back(pt);  // 把任务添加到时间轮去
		_clone[id] = WeakTask(pt); // 同时用weak_ptr把shared_ptr管理起来
	}
	void RefreshTaskInLoop(uint64_t id) // 刷新定时任务
	{
		auto it = _clone.find(id);
		if (it == _clone.end())
		{
			// 没找到 直接返回
			return;
		}
		SharTask pt = it->second.lock(); // 找到保存的定时任务，对该任务进行生成一个shared_ptr,此时引用计数++
		if (!pt)
		{					  // lock() 失败处理
			_clone.erase(it); // 清理无效 weak_ptr
			return;
		}
		int del = pt->TimeOut(); // 获取超时时间
		int ti = (_tick + del) % _capacity;
		_wheel[ti].push_back(pt); // 将任务移动到新的时间点
	}
	void TaskCancelInLoop(uint64_t id) // 取消定时任务销毁
	{
		auto it = _clone.find(id);
		if (it == _clone.end())
		{
			// 没找到 直接返回
			return;
		}
		SharTask pt = it->second.lock();
		if (pt)
			pt->Cancel(); // lock成功进行取消
		_clone.erase(it); // 仅设置 _cancel 而不主动移除 _clone 记录，会导致 _clone 中残留无效数据
						  // 如果后续调用 RefreshTack(id)，会尝试刷新一个已取消的任务（虽然 _cancel = true，但逻辑上不应该再处理）
	}

private:
	int _tick;									   // 每秒移动后的位置，执行该位置的定时任务
	int _capacity;								   // 时间轮的大小
	std::vector<std::vector<SharTask>> _wheel;	   // 时间轮，里面装的是用Sherad_ptr管理起来的定时任务
	std::unordered_map<uint64_t, WeakTask> _clone; // 保存每一个定时任务对象，但是用weak_ptr进行管理sherad_ptr对象，
												   // 防止循环引用，每个定时任务执行完毕后，要进行释放移除
	EventLoop *_loop;
	int _timerfd; // 定时器描述符，可读事件回调就是读取定时器，执行任务
	std::unique_ptr<Channel> _timer_channel;
};